package com.roamcattery.plugins.cmd;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.roamcattery.plugins.engine.LocalVelocityTemplateEngine;
import com.roamcattery.plugins.entity.CustomizeConfig;
import com.roamcattery.plugins.entity.Generator;
import com.roamcattery.plugins.entity.OtherFile;
import com.roamcattery.plugins.load.PropertiesLoadParser;
import com.roamcattery.plugins.load.XmlPropertiesParses;
import com.roamcattery.plugins.load.YamlPropertiesParser;
import com.roamcattery.plugins.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;

import static com.roamcattery.plugins.util.MessageFormatterUtil.info;

/**
 * @author wangwc@wumart.com
 * @version v1.0.0
 * @date 2021/8/20 14:56
 */
@Slf4j
@Mojo(name = "generator")
public class MybatisPlusGeneratorCmd extends AbstractMojo {

    /**
     * 文件位置
     */
    @Parameter(property = "mybatis.generator.configurationFile",
            defaultValue = "${project.basedir}/src/main/resources/application-generator.yml", required = true)
    private File configurationFile;



    public static void main(String[] args) {
        MybatisPlusGeneratorCmd cmd = new MybatisPlusGeneratorCmd();
        try {
            cmd.execute();
        } catch (MojoExecutionException e) {
            e.printStackTrace();
        } catch (MojoFailureException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        info("开始加载文件=================");


        //info("文件路径:" + configurationFile.getAbsolutePath());
        PropertiesLoadParser propertiesLoadParser = new XmlPropertiesParses();
        if (configurationFile.getName().endsWith("yml")) {
            propertiesLoadParser = new YamlPropertiesParser();
        } else if (configurationFile.getName().endsWith("xml")) {
            propertiesLoadParser = new XmlPropertiesParses();
        } else {
            throw new RuntimeException("无效文件");
        }

        Generator generator = propertiesLoadParser.load(configurationFile.getAbsolutePath());
        info("文件加载结束=================");

        DataSourceConfig dataSourceConfig = generator.getDataSourceConfig();
        GlobalConfig globalConfig = generator.getGlobalConfig();
        PackageConfig packageConfig = generator.getPackageConfig();
        StrategyConfig strategyConfig = generator.getStrategyConfig();
        CustomizeConfig customizeConfig = generator.getCustomizeConfig();
        globalConfig.setServiceName("I%sService");
        globalConfig.setServiceImplName("I%sServiceImpl");
        info("Step1：代码生成器");
        AutoGenerator mpg = new AutoGenerator();
        mpg.setGlobalConfig(globalConfig);
        mpg.setDataSource(dataSourceConfig);
        mpg.setPackageInfo(packageConfig);
        // 自定义配置
        if (customizeConfig != null) {
            // 自定义输出配置
            List<FileOutConfig> focList = new ArrayList<>();

            // 自定义配置会被优先输出
            if (StringUtils.isNotBlank(customizeConfig.getXmlFileOutPath())) {
                focList.add(new FileOutConfig(customizeConfig.getXmlTemplatePath()) {
                    @Override
                    public String outputFile(TableInfo tableInfo) {
                        // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                        return customizeConfig.getXmlFileOutPath()
                                + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                    }
                });
            }
            List<OtherFile> otherFileMap = customizeConfig.getFileMap();
            String parentPackage = packageConfig.getParent();
            if (CollectionUtils.isNotEmpty(otherFileMap)) {

                String outDir = globalConfig.getOutputDir();

                for (OtherFile file : otherFileMap) {
                    if (StringUtils.isNotBlank(file.getFileTemplate())) {
                        focList.add(new FileOutConfig(file.getFileTemplate()) {
                            @Override
                            public String outputFile(TableInfo tableInfo) {
                                String fileName = tableInfo.getEntityName();
                                if (StringUtils.isNotBlank(file.getFileName())) {
                                    fileName = String.format(file.getFileName(), tableInfo.getEntityName());
                                }
                                if (!fileName.endsWith(StringPool.DOT_JAVA)) {
                                    fileName = fileName + StringPool.DOT_JAVA;
                                }
                                String path = outDir + "/" + parentPackage + "/" + file.getFilePackage();
                                path = path.replaceAll("\\.", "/");
                                path = path + "/" + fileName;
                                return path;
                            }
                        });
                    }
                }
            }
            //模板参数
            InjectionConfig cfg = new InjectionConfig() {
                @Override
                public void initMap() {
                    JSONObject jsonObject = (JSONObject) JSONObject.toJSON(customizeConfig);
                    Map<String, Object> map = jsonObject.getInnerMap();
                    map.put("parentPackage", parentPackage);
                    this.setMap(map);
                }
            };
            cfg.setFileOutConfigList(focList);
            mpg.setCfg(cfg);
        }
        try {
            LocalVelocityTemplateEngine localVelocityTemplateEngine = new LocalVelocityTemplateEngine();
            localVelocityTemplateEngine.setTemplate_of_local(customizeConfig.getTemplateOfLocalPath());
            mpg.setTemplate(new TemplateConfig().setXml(null));
            mpg.setTemplateEngine(localVelocityTemplateEngine);
            mpg.setStrategy(strategyConfig);
            info("Step6：执行代码生成操作");
            mpg.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}
